const arrayUtil = require('./array')
const numberUtil = require('./numberUtil')
const macdUtil = require('./macdUtil')
const Proxy = require('../proxy')

const Dictionary = Proxy.Dictionary

// 解析数字
function parseValue (val) {
  return parseFloat(val || 0) || 0
}

// 步进格式化
function roundStep (qty, stepSize) {
  stepSize = '' + stepSize
  // Integers do not require rounding
  if (Number.isInteger(qty)) return qty
  const qtyString = parseFloat(qty).toFixed(16)
  const desiredDecimals = Math.max(stepSize.indexOf('1') - 1, 0)
  const decimalIndex = qtyString.indexOf('.')
  return parseFloat(qtyString.slice(0, decimalIndex + desiredDecimals + 1))
}

exports.roundStep = roundStep

// 获取持有数量
exports.getBtbIndexAvailable = function (balance, btbItem) {
  const btbBalance = balance[btbItem.code]
  if (!btbBalance) {
    return 0
  }
  return parseValue(btbBalance.available)
}

exports.getMinAvailableSell = function (available, btbItem, price) {
  // 数量太少
  if (available < btbItem.min_qty) {
    return 0
  }
  // 金额太小
  if ((available * price) < (btbItem.min_notional * 1.1)) {
    return 0
  }
  return roundStep(available, btbItem.step_size || 0)
}

exports.getMinAvailableBuy = function (buyUsdt, btbItem, price, hasUsdt) {
  let quantity = buyUsdt / price
  // 数量太少
  if (quantity < btbItem.min_qty) {
    return false
  }
  // 金额太小
  if ((buyUsdt) < (btbItem.min_notional * 1.1)) {
    return false
  }
  // 所剩的不够用了
  if (buyUsdt >= hasUsdt * 0.95) {
    return false
  }
  return roundStep(buyUsdt / price, btbItem.step_size || 0)
}

exports.countBuyUsdt = async function (btbItem, usdtSum, buyRate, btbIndexUsdtMap, proportionAll, maxR) {
  const pc = await Dictionary.findOne({ key: 'btbPositionConfig' })
  let pr = 1
  if (pc && pc.value) {
    pr = (parseInt(pc.value || 0) || 0) / 100
  }
  maxR = maxR || 1
  // 理论上该币种的标准仓位
  const btbIndexCanUsdt = usdtSum * (btbItem.proportion / proportionAll)
  // 该币种最大仓位
  const btbIndexMaxUsdt = btbIndexCanUsdt * maxR * pr
  // 买入的usdt
  let buyUsdt = btbIndexCanUsdt * buyRate
  // 已经有的usdt
  const btbIndexHasUsdt = btbIndexUsdtMap[btbItem.code]
  if ((btbIndexHasUsdt + buyUsdt) > btbIndexMaxUsdt) {
    buyUsdt = btbIndexMaxUsdt - btbIndexHasUsdt
  }
  return buyUsdt
}

exports.countToRateBuyUsdt = async function (btbItem, usdtSum, buyRate, btbIndexUsdtMap, proportionAll, maxR) {
  const pc = await Dictionary.findOne({ key: 'btbPositionConfig' })
  let pr = 1
  if (pc && pc.value) {
    pr = (parseInt(pc.value || 0) || 0) / 100
  }
  maxR = maxR || 1
  // 理论上该币种的标准仓位
  const btbIndexCanUsdt = usdtSum * (btbItem.proportion / proportionAll)
  // 该币种最大仓位
  const btbIndexMaxUsdt = btbIndexCanUsdt * maxR * buyRate * pr
  // 买入的usdt
  let buyUsdt = btbIndexMaxUsdt
  // 已经有的usdt
  const btbIndexHasUsdt = btbIndexUsdtMap[btbItem.code]
  if ((btbIndexHasUsdt + buyUsdt) > btbIndexMaxUsdt) {
    buyUsdt = btbIndexMaxUsdt - btbIndexHasUsdt
  }
  return buyUsdt
}

exports.getBalanceUsdtInfo = function (myBalance, btbList, priceMap) {
// 总持仓价值USDT
  let usdtSum = parseValue(myBalance['USDT'].available)
  // 所剩的USDT
  let hasUsdt = parseValue(myBalance['USDT'].available)
  // 该币种价值的usdt
  const btbIndexUsdtMap = {}
  btbList.forEach((btbItem) => {
    const usdtKey = `${btbItem.code}USDT`
    // 该笔的持仓
    const available = this.getBtbIndexAvailable(myBalance, btbItem)
    if (!available) {
      return false
    }
    const price = parseValue(priceMap[usdtKey])
    btbIndexUsdtMap[btbItem.code] = price * available
    usdtSum += price * available
  })
  return {
    usdtSum,
    hasUsdt,
    btbIndexUsdtMap
  }
}

exports.getDaySellRate = function (list, macdList) {
  const d = new Date()
  const nowHour = d.getHours()
  // 倒序
  const listLocal = [...list]
  listLocal.reverse()
  // 正序
  const list5 = arrayUtil.getAverageList(listLocal, 5)
  const list10 = arrayUtil.getAverageList(listLocal, 10)
  const list20 = arrayUtil.getAverageList(listLocal, 20)
  const diff5to10List = []
  list5.forEach((v, i) => {
    diff5to10List.push(v - list10[i])
  })
  const diff5to20List = []
  list5.forEach((v, i) => {
    diff5to20List.push(v - list20[i])
  })
  const lastIndex = list5.length - 1
  // const diffC = numberUtil.countDifferenceRate(list5[lastIndex], list10[lastIndex])
  const diff5C20 = numberUtil.countDifferenceRate(list5[lastIndex], list20[lastIndex])
  const diff5To10Macd = macdUtil.getDiff5To10Macd(macdList, diff5to10List, diff5to20List, lastIndex)
  // 卖出
  let sellRate = 0
  if (diff5To10Macd.ismacdValToDown || diff5To10Macd.isDiff5to10ValToDown) {
    if (diff5To10Macd.sellTwo) {
      // 晚上8点卖
      if (nowHour === 20) {
        sellRate = 1
      }
    } else {
      // 7点卖
      if (nowHour === 7) {
        if (diff5C20 > 0) {
          sellRate = 0.5
        } else {
          sellRate = 1
        }
      }
    }
  }
  return sellRate
}

exports.getDayBuyRate = function (list, macdList) {
  const d = new Date()
  const nowHour = d.getHours()
  // 倒序
  const listLocal = [...list]
  listLocal.reverse()
  // 正序
  const list5 = arrayUtil.getAverageList(listLocal, 5)
  const list10 = arrayUtil.getAverageList(listLocal, 10)
  const list20 = arrayUtil.getAverageList(listLocal, 20)
  const diff5to10List = []
  list5.forEach((v, i) => {
    diff5to10List.push(v - list10[i])
  })
  const diff5to20List = []
  list5.forEach((v, i) => {
    diff5to20List.push(v - list20[i])
  })
  const lastIndex = list5.length - 1
  // const diffC = numberUtil.countDifferenceRate(list5[lastIndex], list10[lastIndex])
  const diff5C20 = numberUtil.countDifferenceRate(list5[lastIndex], list20[lastIndex])
  const diff5To10Macd = macdUtil.getDiff5To10Macd(macdList, diff5to10List, diff5to20List, lastIndex)
  // 买入
  let buyRate = 0
  // 转下的优先级高于转上
  if (diff5To10Macd.ismacdValToDown || diff5To10Macd.isDiff5to10ValToDown) {
    return buyRate
  }
  if (diff5To10Macd.ismacdValToUp || diff5To10Macd.isDiff5to10ValToUp) {
    if (diff5To10Macd.buyTwo) {
      // 晚上8点卖
      if (nowHour === 20) {
        buyRate = 1
      }
    } else {
      // 7点卖
      if (nowHour === 7) {
        if (diff5C20 > 0) {
          if (diff5To10Macd.macdVal < 0) {
            buyRate = 0.5
          } else {
            buyRate = 1
          }
        } else {
          buyRate = 0.5
        }
      }
    }
  }
  return buyRate
}

exports.getAllDown = function (list, macdList) {
  // 倒序
  const listLocal = [...list]
  listLocal.reverse()
  // 正序
  const list5 = arrayUtil.getAverageList(listLocal, 5)
  const list10 = arrayUtil.getAverageList(listLocal, 10)
  const diff5to10List = []
  list5.forEach((v, i) => {
    diff5to10List.push(v - list10[i])
  })
  const lastIndex = list5.length - 1
  // 看两天，因为第一天的波动不准，变化很大
  return (macdList[lastIndex] < 0) && (macdList[lastIndex - 1] < 0) && (diff5to10List[lastIndex] < 0) && (diff5to10List[lastIndex - 1] < 0)
}

exports.getSDown = function (list, macdList) {
  // 倒序
  const listLocal = [...list]
  listLocal.reverse()
  // 正序
  const list5 = arrayUtil.getAverageList(listLocal, 5)
  const list10 = arrayUtil.getAverageList(listLocal, 10)
  const diff5to10List = []
  list5.forEach((v, i) => {
    diff5to10List.push(v - list10[i])
  })
  const lastIndex = list5.length - 1
  // 看两天，因为第一天的波动不准，变化很大
  // 这个策略并不是为了很敏感得卖出，而是为了，明明跌了好久，怎么还怎么搞仓位
  return (macdList[lastIndex] < 0) && (macdList[lastIndex - 1] < 0) && (diff5to10List[lastIndex] < 0) && (diff5to10List[lastIndex - 1] < 0)
}

exports.getAllUp = function (list, macdList) {
  // 倒序
  const listLocal = [...list]
  listLocal.reverse()
  // 正序
  const list5 = arrayUtil.getAverageList(listLocal, 5)
  const list10 = arrayUtil.getAverageList(listLocal, 10)
  const diff5to10List = []
  list5.forEach((v, i) => {
    diff5to10List.push(v - list10[i])
  })
  const lastIndex = list5.length - 1
  // 看两天，因为第一天的波动不准，变化很大
  return (macdList[lastIndex] > 0) && (macdList[lastIndex - 1] > 0) && (diff5to10List[lastIndex] > 0) && (diff5to10List[lastIndex - 1] > 0)
}

exports.getDayDownHDownRate = function (list, macdList, listH, macdListH) {
  if (this.getSDown(list, macdList) && this.getAllDown(listH, macdListH)) {
    return 1
  }
  return 0
}

exports.getDayUpHUpRate = function (list, macdList, listH, macdListH) {
  if (this.getAllUp(list, macdList) && this.getAllUp(listH, macdListH)) {
    return 0.1
  }
  return 0
}

exports.getDayDown = function (list, macdList) {
  return this.getSDown(list, macdList)
}

exports.getDayUp = function (list, macdList) {
  return this.getAllUp(list, macdList)
}

exports.redNowLittleDown = function (macdList) {
  let lastIndex = macdList.length - 1
  if ((macdList[lastIndex] > 0) &&
    (macdList[lastIndex - 1] < 0) &&
    (macdList[lastIndex - 5] > 0)
  ) {
    return true
  }
  return false
}

exports.getMacdDiff5To10Info = function (list, macdList) {
  // 倒序
  const listLocal = [...list]
  listLocal.reverse()
  // 正序
  const list5 = arrayUtil.getAverageList(listLocal, 5)
  const list10 = arrayUtil.getAverageList(listLocal, 10)
  const list20 = arrayUtil.getAverageList(listLocal, 20)
  const diff5to10List = []
  list5.forEach((v, i) => {
    diff5to10List.push(v - list10[i])
  })
  const diff5to20List = []
  list5.forEach((v, i) => {
    diff5to20List.push(v - list20[i])
  })
  const lastIndex = list5.length - 1
  const diffC = numberUtil.countDifferenceRate(list5[lastIndex], list10[lastIndex])
  const diff5C20 = numberUtil.countDifferenceRate(list5[lastIndex], list20[lastIndex])
  const diff5To10Macd = macdUtil.getDiff5To10Macd(macdList, diff5to10List, diff5to20List, lastIndex)
  let day = 0
  const newList5 = [...list5]
  newList5.reverse()
  const newList10 = [...list10]
  newList10.reverse()
  for (let i = 0; i < newList5.length; i++) {
    const diff = numberUtil.countDifferenceRate(newList5[i], newList10[i])
    if (diffC > 0) {
      if (diff >= 0) {
        day++
      } else {
        break
      }
    } else if (diffC < 0) {
      if (diff <= 0) {
        day++
      } else {
        break
      }
    }
  }
  const macdVal = macdList[lastIndex]
  let macdDay = 0
  const newMacdList = [...macdList]
  newMacdList.reverse()
  for (let i = 0; i < newMacdList.length; i++) {
    const diff = newMacdList[i]
    if (macdVal > 0) {
      if (diff >= 0) {
        macdDay++
      } else {
        break
      }
    } else if (macdVal < 0) {
      if (diff <= 0) {
        macdDay++
      } else {
        break
      }
    }
  }
  return {
    ...diff5To10Macd,
    diff5to10Days: day,
    macdDays: macdDay,
    macdVal,
    diff5to10: diff5to10List[lastIndex],
    diff5C20
  }
}
